<?php

/**
 * Ignus Framework
 *
 * @author Sergey Palyanov <sergey.palyanov@gmail.com>
 * @link http://code.google.com/p/ignus-php/
 * @license http://apache.org/licenses/LICENSE-2.0
 * @package Ignus
 * @subpackage App
 * @since 0.1
 */

namespace Ignus;

use Ignus\Log\LogManager;
use Ignus\Log\Logger;

/**
 * @package Ignus
 * @subpackage App
 * @since 0.1
 */
abstract class App
{
    /**
     * Work modes
     */
    const MODE_PRODUCTION = 'prod';
    const MODE_DEVELOPMENT = 'dev';

    /**
     * Ignus Framework version number
     */
    const VERSION = '0.8.0';

    /**
     * @var string Path to application directory
     */
    private static $appDir;

    /**
     * @var string Current mode (prod or dev)
     */
    private static $mode;

    /**
     * @var \Ignus\Router
     */
    private static $router;

    /**
     * Loads class with specified name
     * @param string $class Class name
     * @todo Check file existence in include path
     */
    public static function loadClass($class)
    {
        $path = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';

        if (!self::isProduction()) {
            $classExists = false;
            $dirs = explode(PATH_SEPARATOR, get_include_path());
            foreach ($dirs as $dir) {
                if (is_readable($dir . DIRECTORY_SEPARATOR . $path)) {
                    $classExists = true;
                    break;
                }
            }

            if (!$classExists) {
                throw new Exception('Class "' . $class . '" does not exists');
            }
        }

        include_once $path;
    }

    /**
     * Get full path to application directory
     * @param string $subdir Directory name
     * @return string
     */
    public static function getAppDir($subdir)
    {
        return self::$appDir . $subdir . DIRECTORY_SEPARATOR;
    }

    /**
     * Form path to file $filename within $subdir
     * @param string $subdir Directory name
     * @param string $filename File name
     * @return string
     */
    public static function getPath($subdir, $filename)
    {
        return self::getAppDir($subdir) . $filename;
    }

    /**
     * Starts request processing
     * @param \Ignus\Router $router Router object
     * @return void
     */
    public static function run(Router $router)
    {
        self::$router = $router;

        try {
            Configurator::initApp();
            Configurator::initRoutes($router);
            $router->run();
        }
        catch (Exception $e) {
            $className = $e->getClassName();
            LogManager::getLogger($className)->error($e);
            echo $e->getMessage();
        }
        catch (\Exception $e) {
            echo $e->getMessage();
        }
    }

    /**
     * Returns true is application is in production mode
     * @return boolean
     */
    public static function isProduction()
    {
        return self::$mode == self::MODE_PRODUCTION;
    }

    /**
     * @param string $dir Application directory
     * @param string $mode Working mode
     * @return void
     */
    public static function init($dir, $mode = self::MODE_DEVELOPMENT)
    {
        $dir = realpath($dir);
        if (substr($dir, -1) != DIRECTORY_SEPARATOR)
            $dir .= DIRECTORY_SEPARATOR;

        self::$appDir = $dir;
        self::$mode = $mode;
        set_error_handler('self::errorHandler');
        spl_autoload_register('self::loadClass');
    }

    /**
     * Framework-global error handler
     * @param int $severity Error severity
     * @param string $message Error message
     * @param string $file Filename that the error was raised in
     * @param int $line Line number the error was raised at
     * @return void
     * @since 0.8.0
     */
    public static function errorHandler($severity, $message, $file = '', $line = 0)
    {
        throw new Exception($message, 0, null, $file, $line);
    }

    /**
     * Returns current request router
     * @return \Ignus\Router
     */
    public static function getRouter()
    {
        return self::$router;
    }
}
